package ldh.im.fxgui.controller;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
import ldh.im.fxbase.util.ThreadPoolUtil;
import ldh.im.fxbase.cell.ObjectListCell;
import ldh.im.fxbase.cell.ObjectStringConverter;
import ldh.im.fxbase.fxanimations.FadeOutTransition;
import ldh.im.fxgui.dto.LoginDto;
import ldh.im.fxbase.help.MovableHelper;
import ldh.im.fxbase.pojo.User;
import ldh.im.fxbase.util.StageUtil;
import ldh.im.fxgui.service.HttpService;
import ldh.im.fxgui.util.UiUtil;
import org.apache.commons.lang3.StringUtils;
import org.kordamp.ikonli.fontawesome.FontAwesome;
import org.kordamp.ikonli.javafx.FontIcon;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoginController implements Initializable {

    private static final Logger LOGGER = Logger.getLogger(LoginController.class.getName());

    @FXML public Button closeBtn;
    @FXML public ComboBox<User> userNameComboBox;
    @FXML public PasswordField passwordField;
    @FXML public Pane contentPane;
    @FXML public Pane root;
    @FXML private Button loginBtn;
    @FXML private ProgressIndicator loginProgress;
    @FXML private Label errorLoginTip;

    private Future loginFuture = null;

    private Consumer<?> consumer = null;

    private Stage loginStage = null;
    private boolean isCancel = false;

    public Scene createScene() {
        Scene scene = new Scene(root, 450, 330);
        scene.setFill(Color.TRANSPARENT);
        scene.getStylesheets().add(this.getClass().getResource("/css/login.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/bootstrapfx.css").toExternalForm());
        return scene;
    }

    public void setLoginStage(Stage stage) {
        this.loginStage = stage;
    }

    @FXML
    public void close() {
        close(null, (Void)->{
            StageUtil.close();
            return null;
        });
    }

    @FXML
    public void loginBtn() {
        if(!checkForm()) {
            return;
        }
        loginBtn.setDisable(true);
        loginProgress.setVisible(true);
        errorLoginTip.setText("登录中......");
        isCancel = false;
        loginFuture = ThreadPoolUtil.submit(()->{
            boolean isLoginSuccess = loginAction();
            if (!isLoginSuccess) return;
            if (isCancel) {
                resetLogin(null);
                return;
            }
            Platform.runLater(()->{
                close((Void)->{
                    if (consumer != null) {
                        consumer.accept(null);
                    }
                }, null);
            });
        }, (errorMsg)->{
            LOGGER.log(Level.SEVERE, errorMsg);
            String errorTip = isCancel ? "登录被取消" : "登录错误";
            resetLogin(errorTip);
        });
    }

    @FXML
    public void cancelAct() {
        isCancel = true;
        if (loginFuture != null) loginFuture.cancel(true);
        loginBtn.setDisable(false);
        loginProgress.setVisible(false);
        errorLoginTip.setText("登录被取消");
    }

    private void resetLogin(String loginErrorMsg) {
        loginFuture = null;
        isCancel = false;
        String errorTip = loginErrorMsg != null ? loginErrorMsg : "";
        Platform.runLater(()-> {
            loginBtn.setDisable(false);
            errorLoginTip.setText(errorTip);
            loginProgress.setVisible(false);
        });
    }

    private boolean loginAction() {
        try {
            String name = userNameComboBox.getValue().getUserName();
            String password = passwordField.getText();
            LoginDto loginDto = HttpService.login(name, password);
            return true;
        } catch (Exception e) {
            UiUtil.uiHandle((Void)->{
                errorLoginTip.setText(e.getMessage());
                loginBtn.setDisable(false);
                loginProgress.setVisible(false);
            });
        }
        return true;
    }

    private boolean checkForm() {
        if (userNameComboBox.getValue() == null || StringUtils.isEmpty(userNameComboBox.getValue().getUserName())) {
            errorLoginTip.setText("用户名不能为空");
            return false;
        }
        if (StringUtils.isEmpty(passwordField.getText())) {
            errorLoginTip.setText("密码不能为空");
            return false;
        }
        return true;
    }

    public Pane getRoot() {
        return root;
    }

    public void setConsumer(Consumer<?> consumer) {
        this.consumer = consumer;
    }

    private void close(Consumer<?> consumer, Callback callback) {
        FadeOutTransition fadeOutTransition = new FadeOutTransition(root);
        fadeOutTransition.setOnFinished(e->{
            if (callback != null) callback.call(null);
            if(loginStage != null) loginStage.close();
            if (consumer != null) {
                consumer.accept(null);
            }
        });
        fadeOutTransition.playFromStart();
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        MovableHelper.movable(contentPane);

        Rectangle clip = new Rectangle();
        clip.widthProperty().bind(root.widthProperty());
        clip.heightProperty().bind(root.heightProperty());
        clip.setArcWidth(15);
        clip.setArcHeight(15);
        root.setClip(clip);

        userNameComboBox.setConverter(new ObjectStringConverter<User>(user->{
            if(user == null) return null;
            String u = user.getUserName();
            return u;
        }));

        userNameComboBox.getSelectionModel().selectedItemProperty().addListener((ob, o, n)->{
            passwordField.setText(new String(userNameComboBox.getSelectionModel().getSelectedItem().getPassword()));
        });

        userNameComboBox.setCellFactory(new ObjectListCell<User>(user->{
            Label label = new Label();
            label.setPadding(new Insets(0, 0, 0, 10));
            label.setText(user.getUserName());
            FontIcon fontIcon = FontIcon.of(FontAwesome.findByDescription("fa-user"));
            if (user.getUserName().equals("")) {
                fontIcon = FontIcon.of(FontAwesome.findByDescription("fa-user-plus"));
            }

            label.setGraphic(fontIcon);
            return label;
        }));

        User user = new User();
        user.setUserName("test");
        user.setPassword("123456".toCharArray());

        User nullUser = new User();
        nullUser.setPassword("".toCharArray());
        nullUser.setUserName("");

        userNameComboBox.getItems().addAll(nullUser, user);
    }
}
